/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nanosn.coffeemaker.application.commands;

import com.nanosn.coffeemaker.Project;
import com.nanosn.coffeemaker.databaseproject.persistence.TemporaryJDBCConfiguration;
import com.nanosn.coffeemaker.exceptions.ApplicationNotFoundException;
import com.nanosn.util.parsers.commandline.Command;
import java.io.File;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.meta.MappingTool;
import org.apache.openjpa.jdbc.schema.SchemaTool;

/**
 * 
 * @author selkhateeb
 */
public class Sql implements Command {

    private String getApplicationName(String[] args) throws Exception {
        if (args.length < 2) {
            throw new Exception("Application name is not specified");
        }
        return args[1];
    }

    public void run(String[] args) throws Exception {

        List<String> apps = Arrays.asList(Project.getSettings().getInstalledApps());
        String appname = Project.getSettings().getRootPackage() + "." + getApplicationName(args);

        if (!apps.contains(appname)) {
            throw new ApplicationNotFoundException(appname);
        }

        new Compile().run(new String[]{});
        doMappingTool(getApplicationName(args));
    }

    public String getHelp() {
        return "Prints the CREATE TABLE SQL statements for "
               + "the given app name(s)";
    }

    public void doMappingTool(String appName) throws Exception {

        JDBCConfigurationImpl conf = new TemporaryJDBCConfiguration();

        //ClassLoader loader = Project.getClassLoader();
        ClassLoader loader = this.getClass().getClassLoader();
        String[] classList = getClassListFor(appName);
        Writer w = new OutputStreamWriter(System.out);

        MappingTool.Flags flags = new MappingTool.Flags();
        flags.action = MappingTool.ACTION_ADD;
        flags.schemaAction = SchemaTool.ACTION_BUILD;
        flags.sqlWriter = w;
        flags.ignoreErrors = false;
        flags.readSchema = false;
        flags.dropTables = false;
        flags.openjpaTables = false;
        flags.dropSequences = false;
        flags.sequences = false; // true;
        flags.primaryKeys = false;
        flags.foreignKeys = false;
        flags.indexes = false;

        MappingTool.run(conf, classList, flags, loader);
        w.flush();
        w.close();

        /* TODO: Find another way to delete the derby.log file to keep things
         *      clean
         *      .. but for now ..
         */
        File derby_log = new File("derby.log");
        if (derby_log.exists()) {
            derby_log.delete();
        }
    }

    private String[] getClassListFor(String applicationName) throws Exception {

        String developmentDir = Project.getDevelopmentDirectory() + Project.getSettings().getRootPackage();
        File modelsDirectory = new File(developmentDir, applicationName + File.separator + "models");
        System.out.println("modelsDirectory=" +modelsDirectory);
        if (!modelsDirectory.exists() || modelsDirectory.list().length == 0) {
            //No files .. get out
            throw new Exception("No models exits.. Nothing to do..");
            //return null;
        }
//        String directory = Project.getProjectParentDirectory();
        String directory = Project.getDevelopmentDirectory();

        List<String> result = new ArrayList<String>();
        for (File file : modelsDirectory.listFiles()) {
            if (!file.getAbsolutePath().endsWith(".class")) {
                continue;
            }
            System.out.println("directory= " + directory);
            String className = file.getAbsolutePath().replace(directory, "");
            className = className.replace(".class", "");
            className = className.replace(File.separator, ".");

            System.out.println(className);

            result.add(className);
        }
        return result.toArray(new String[result.size()]);
    }
}
